#pragma once
#include <iostream>
#include <vector>
#include <unistd.h>
#include "Mutex.hpp"
#include "Sem.hpp"
namespace RingQueueModule
{
    using namespace MutexModule;
    using namespace SemModule;
    int default_cp = 5;
    template <class T>
    class RingQueue
    {
    public:
        RingQueue(int cp = default_cp)
            : _cp(cp),
              _rq(cp),
              _space(cp),
              _data(0),
              _p_pos(0),
              _c_pos(0)
        {
        }
        ~RingQueue()
        {
        }
        void EQueue(T data)
        {
            // 生产者
            _space.P();

            {
                LockGuard lockguard(_p_mutex);
                _rq[_c_pos] = data;
                _c_pos++;
                _c_pos %= _cp;
            }

            _data.V();
        }
        void Pop(T *data)
        {
            // 消费者
            _data.P();
            {
                LockGuard lockguard(_c_mutex);
                *data = _rq[_p_pos];
                _p_pos++;
                _p_pos %= _cp;
            }
            _space.V();
        }

    private:
        int _cp;            // 容量
        std::vector<T> _rq; // 环形队列
        Sem _space;         // 空间信号量
        Sem _data;          // 数据信号量
        int _p_pos;         // 生产者位置
        int _c_pos;         // 消费者位置
        Mutex _c_mutex;     // 消费者之间的锁
        Mutex _p_mutex;     // 生产者之间的锁
    };
}